package hn.cch.spring_boot_rest_quartz.service;

import hn.cch.spring_boot_rest_quartz.entity.QuartzTrigger;
import org.quartz.*;
import org.quartz.impl.matchers.GroupMatcher;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.quartz.QuartzJobBean;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.util.*;


@Service
public class QuartzService {

    public static Logger logger = LoggerFactory.getLogger(QuartzService.class);


    @Autowired
    private Scheduler scheduler;

    @PostConstruct
    public void startScheduler() {
        try {
            scheduler.start();
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
    }

    /**
     * 调度任务
     *
     * @param quartzTrigger
     */
    public boolean scheduleJob(QuartzTrigger quartzTrigger) {

        try {
            Class<QuartzJobBean> jobClass = (Class<QuartzJobBean>) Class.forName(quartzTrigger.getJobClass());
            return scheduleJob(jobClass, quartzTrigger.getJobName(), quartzTrigger.getJobGroup(), quartzTrigger.getJobCron(), quartzTrigger.getJobData());
        } catch (ClassNotFoundException e) {
            logger.error(e.getMessage());
            return false;
        }

    }

    /**
     * 调度任务
     *
     * @param jobName
     * @param jobGroup
     */
    public boolean scheduleJob(Class<? extends QuartzJobBean> jobClass, String jobName, String jobGroup, String jobCron, Map jobData) {
        JobDetail jobDetail = JobBuilder.newJob(jobClass)
                .withIdentity(jobName, jobGroup).build();
        jobDetail.getJobDataMap().putAll(jobData);

        CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(jobCron);
        Trigger trigger = TriggerBuilder.newTrigger()
                .withSchedule(cronScheduleBuilder)
                .withIdentity(jobName, jobGroup).build();
        logger.info(jobName + "_cron:" + jobCron);
        try {
            Date date = scheduler.scheduleJob(jobDetail, trigger);
            if (date != null) {
                logger.info(jobName + "_date:" + date.toString());
                return true;
            } else {
                logger.error(jobName + ":" + "schedule failed");
                return false;
            }
        } catch (SchedulerException e) {
            logger.error(e.getMessage());
            return false;
        }
    }

    /**
     * 重设任务
     *
     * @param jobName
     * @param jobGroup
     */
    public boolean rescheduleJob(String jobName, String jobGroup, String jobCron) {

        TriggerKey triggerKey = TriggerKey.triggerKey(jobName, jobGroup);
        CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(jobCron);
        Trigger trigger = TriggerBuilder.newTrigger()
                .withSchedule(cronScheduleBuilder)
                .withIdentity(jobName, jobGroup).build();
        logger.info(jobName + "_cron:" + jobCron);

        try {
            Date date = scheduler.rescheduleJob(triggerKey, trigger);
            if (date != null) {
                logger.info(jobName + "_date:" + date.toString());
                return true;
            } else {
                logger.error(jobName + ":" + "reschedule failed");
                return false;
            }
        } catch (SchedulerException e) {
            logger.error(e.getMessage());
            return false;
        }
    }

    /**
     * 删除任务
     *
     * @param jobName
     * @param jobGroup
     */
    public boolean deleteJob(String jobName, String jobGroup) {
        try {
            if (scheduler.deleteJob(new JobKey(jobName, jobGroup))) {
                return true;
            } else {
                return false;
            }
        } catch (Exception e) {
            logger.error(e.getMessage());
            return false;
        }
    }

    /**
     * 暂停任务
     *
     * @param jobName
     * @param jobGroup
     */
    public boolean pauseJob(String jobName, String jobGroup) {
        try {
            scheduler.pauseJob(new JobKey(jobName, jobGroup));
            return true;
        } catch (SchedulerException e) {
            logger.error(e.getMessage());
            return false;
        }
    }

    /**
     * 恢复任务
     *
     * @param jobName
     * @param jobGroup
     */
    public boolean resumeJob(String jobName, String jobGroup) {
        try {
            scheduler.resumeJob(new JobKey(jobName, jobGroup));
            return true;
        } catch (SchedulerException e) {
            logger.error(e.getMessage());
            return false;
        }
    }

    /**
     * 触发任务
     *
     * @param jobName
     * @param jobGroup
     */
    public boolean triggerJob(String jobName, String jobGroup) {
        try {
            scheduler.triggerJob(new JobKey(jobName, jobGroup));
            return true;
        } catch (SchedulerException e) {
            logger.error(e.getMessage());
            return false;
        }
    }

    /**
     * 查询所有任务触发
     */
    public List<QuartzTrigger> getAllJob() {

        List<QuartzTrigger> quartzTriggers = new ArrayList<>();
        try {
            Set<JobKey> jobKeySet = scheduler.getJobKeys(GroupMatcher.anyJobGroup());
            for (JobKey jobKey : jobKeySet) {
                QuartzTrigger quartzTrigger = new QuartzTrigger();
                quartzTrigger.setJobName(jobKey.getName());
                quartzTrigger.setJobGroup(jobKey.getGroup());

                JobDetail jobDetail = scheduler.getJobDetail(jobKey);
                quartzTrigger.setJobClass(jobDetail.getJobClass().getName());
                JobDataMap jobDataMap = jobDetail.getJobDataMap();
                String[] keys = jobDataMap.getKeys();
                Map<String, Object> jobData = new HashMap<>();
                for (String key : keys) {
                    Object value = jobDataMap.get(key);
                    Object object = jobData.put(key, value);
                    // logger.info("object:" + object);
                }
                quartzTrigger.setJobData(jobData);

                List<? extends Trigger> triggers = scheduler.getTriggersOfJob(jobKey);
                logger.info("triggers_size:" + triggers.size());
                for (Trigger trigger : triggers) {

                    Trigger.TriggerState triggerState = scheduler.getTriggerState(trigger.getKey());
                    quartzTrigger.setJobState(triggerState.name());

                    if (trigger instanceof CronTrigger) {
                        CronTrigger cronTrigger = (CronTrigger) trigger;
                        quartzTrigger.setJobCron(cronTrigger.getCronExpression());
                    }

                }
                quartzTriggers.add(quartzTrigger);
            }


        } catch (SchedulerException e) {
            e.printStackTrace();
        }

        return quartzTriggers;

    }

    /**
     * 查询单个任务触发
     *
     * @param jobName
     * @param jobGroup
     * @return
     */
    public QuartzTrigger getJob(String jobName, String jobGroup) {

        QuartzTrigger quartzTrigger = null;
        try {

            JobKey jobKey = new JobKey(jobName, jobGroup);
            JobDetail jobDetail = scheduler.getJobDetail(jobKey);

            if (jobDetail != null) {
                quartzTrigger = new QuartzTrigger();
                quartzTrigger.setJobName(jobName);
                quartzTrigger.setJobGroup(jobGroup);
                quartzTrigger.setJobClass(jobDetail.getJobClass().getName());
                JobDataMap jobDataMap = jobDetail.getJobDataMap();
                String[] keys = jobDataMap.getKeys();
                Map<String, Object> jobData = new HashMap<>();
                for (String key : keys) {
                    Object value = jobDataMap.get(key);
                    Object object = jobData.put(key, value);
                    // logger.info("object:" + object);
                }
                quartzTrigger.setJobData(jobData);

                List<? extends Trigger> triggers = scheduler.getTriggersOfJob(jobKey);
                logger.info("triggers_size:" + triggers.size());
                for (Trigger trigger : triggers) {

                    Trigger.TriggerState triggerState = scheduler.getTriggerState(trigger.getKey());
                    quartzTrigger.setJobState(triggerState.name());

                    if (trigger instanceof CronTrigger) {
                        CronTrigger cronTrigger = (CronTrigger) trigger;
                        quartzTrigger.setJobCron(cronTrigger.getCronExpression());
                    }

                }
            }
        } catch (SchedulerException e) {
            e.printStackTrace();
        }

        return quartzTrigger;

    }


}
